/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package sk.lieskove.jianghongtiao.common.extract.text;

import org.apache.log4j.Logger;
import org.apache.poi.POIOLE2TextExtractor;
import org.apache.poi.POITextExtractor;
import org.apache.poi.POIXMLTextExtractor;
import org.apache.poi.extractor.ExtractorFactory;
import org.apache.poi.hdgf.extractor.VisioTextExtractor;
import org.apache.poi.hpbf.extractor.PublisherTextExtractor;
import org.apache.poi.hslf.extractor.PowerPointExtractor;
import org.apache.poi.hsmf.extractor.OutlookTextExtactor;
import org.apache.poi.hssf.extractor.ExcelExtractor;
import org.apache.poi.hwpf.extractor.Word6Extractor;
import org.apache.poi.hwpf.extractor.WordExtractor;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.poifs.filesystem.OfficeXmlFileException;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.xslf.extractor.XSLFPowerPointExtractor;
import org.apache.poi.xssf.extractor.XSSFExcelExtractor;
import org.apache.poi.xwpf.extractor.XWPFWordExtractor;
import org.apache.xmlbeans.XmlException;
import sk.lieskove.jianghongtiao.common.utils.PropertiesUtils;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.Serializable;

/**
 * 
 * @author xjuraj e-mail: jjurco.sk_gmail.com
 */
public class MSOffice2Text implements Serializable, TextExtractor {

    private transient Logger log = Logger.getLogger(MSOffice2Text.class);
    private transient PropertiesUtils pu = new PropertiesUtils(MSOffice2Text.class);

    @Override
    public String extractText(File inputFile) {
        log.debug("Enter MSOffice2Text with file: " + inputFile.getAbsolutePath());
        try {
            POITextExtractor extractor = null;
            String extractedText = null;
            FileInputStream fis = null;
            try{
                fis = new FileInputStream(inputFile);
                POIFSFileSystem fileSystem = new POIFSFileSystem(fis);
                POIOLE2TextExtractor poiOleExtractor =
                        ExtractorFactory.createExtractor(fileSystem);
                extractor = poiOleExtractor;
                POITextExtractor[] embeddedExtractors =
                        ExtractorFactory.getEmbededDocsTextExtractors(poiOleExtractor);

                //at first, extract main content
                extractedText = getText(extractor);
                // Then a List of extractors for any embedded Excel, Word, PowerPoint
                // or Visio objects embedded into it.
                String extr = "";
                for (POITextExtractor textExtractor : embeddedExtractors) {
                    extractedText += getText(textExtractor);
                }
            } catch(OfficeXmlFileException ex){
                if(fis!=null){
                    try{
                        fis.close();
                    } catch(IOException e){
                        log.error("Cannot close input stram for the file: "+
                                inputFile.getAbsolutePath());
                    }
                }
                fis = new FileInputStream(inputFile);
                //I know, this is the most stupid thing, but I'm so sorry for this
                //I'm too lazy to search for another solution now. Maybe later...
                POIXMLTextExtractor poiXmlExtractor =
                        ExtractorFactory.createExtractor(OPCPackage.open(fis));
                extractor = poiXmlExtractor;
                //at first, extract main content
                extractedText = getText(extractor);
                return extractedText.trim();
            } finally{
                if(fis!=null){
                    try{
                        fis.close();
                    } catch(IOException e){
                        log.error("Cannot close input stram for the file: "+
                                inputFile.getAbsolutePath());
                    }
                }
            }
            log.debug("MSOffice2Text extracted: " + extractedText.length() + " characters.");
            return extractedText.trim();
        } catch (IOException ex) {
            log.error("I/O exception the file: " + inputFile.getAbsolutePath());
        } catch (InvalidFormatException ex) {
            log.error("Invalid format: " + ex.getMessage());
        } catch (OpenXML4JException ex) {
            log.error("OpenXML4JException: " + ex.getMessage());
        } catch (XmlException ex) {
            log.error("XML exception: " + ex.getMessage());
        } catch (OfficeXmlFileException ex) {
            log.error("OfficeXmlFileException exception for file: " + inputFile.getAbsolutePath());
            throw ex;
        }
        return null;
    }

    private String getText(POITextExtractor textExtractor) {
        String extractedText = "";
        if (textExtractor instanceof PublisherTextExtractor) {
//            extr = "publisher";
            PublisherTextExtractor publisherTextExtractor = (PublisherTextExtractor) textExtractor;
            extractedText = publisherTextExtractor.getText();
        } else if (textExtractor instanceof OutlookTextExtactor) {
//            extr = "outlook";
            OutlookTextExtactor outlookTextExtactor = (OutlookTextExtactor) textExtractor;
            extractedText = outlookTextExtactor.getText();
        } else if (textExtractor instanceof Word6Extractor) {
//            extr = "word6";
            Word6Extractor word6Extractor = (Word6Extractor) textExtractor;
            extractedText = word6Extractor.getText();
        } else if (textExtractor instanceof WordExtractor) {
//            extr = "word";
            WordExtractor wordExtractor = (WordExtractor) textExtractor;
            extractedText = wordExtractor.getText();
        } else if (textExtractor instanceof ExcelExtractor) {
//            extr = "excel";
            ExcelExtractor excelExtractor = (ExcelExtractor) textExtractor;
            excelExtractor.setIncludeBlankCells(true);
            excelExtractor.setIncludeCellComments(true);
            excelExtractor.setIncludeHeadersFooters(true);
            excelExtractor.setIncludeSheetNames(true);
            extractedText = excelExtractor.getText();
        } else if (textExtractor instanceof PowerPointExtractor) {
//            extr = "powerpoint";
            PowerPointExtractor powerPointExtractor =
                    (PowerPointExtractor) textExtractor;
            extractedText = powerPointExtractor.getText(true, true, true, true);
        } else if (textExtractor instanceof VisioTextExtractor) {
//            extr = "visio";
            VisioTextExtractor visioTextExtractor =
                    (VisioTextExtractor) textExtractor;
            extractedText = visioTextExtractor.getText();
        } else if (textExtractor instanceof XSLFPowerPointExtractor){
            XSLFPowerPointExtractor extractor = 
                    (XSLFPowerPointExtractor) textExtractor;
            extractedText = extractor.getText();
        } else if (textExtractor instanceof XSSFExcelExtractor){
            XSSFExcelExtractor extractor = 
                    (XSSFExcelExtractor) textExtractor;
            extractedText = extractor.getText();
        } else if (textExtractor instanceof XWPFWordExtractor){
            XWPFWordExtractor extractor = 
                    (XWPFWordExtractor) textExtractor;
            extractedText = extractor.getText();
        }
        return extractedText;
    }
}
